package io.gitee.zhucan123.core.infrastructure.util;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.util.RawValue;

import java.util.Iterator;
import java.util.Map;
import java.util.function.Function;

/**
 * @author guodu
 * @date 2019/10/16
 */
public class JsonUtils {

  /**
   * 使用系统中的objectMapper获取到正确的字段名，因为字段名也许是驼峰，也许是蛇形
   */
  public static String getJsonFieldName(ObjectMapper objectMapper, String fieldName) {
    PropertyNamingStrategy namingStrategy = objectMapper.getPropertyNamingStrategy();
    if(namingStrategy == null) {
      return fieldName;
    }
    return namingStrategy.nameForField(null, null, fieldName);
  }

  public static Function<String, String> SNAKE_TO_SMALL_CAMEL = name -> {
    StringBuilder sb = new StringBuilder(name.length());
    char prevChar = '\0';
    for(int i = 0; i < name.length(); i++) {
      char c = name.charAt(i);
      if(c != '_') {
        if(prevChar == '_') {
          c = Character.toUpperCase(c);
        }
        sb.append(c);
      }
      prevChar = c;
    }
    return sb.toString();
  };

  /**
   * 转换json中所有的key.
   */
  public static JsonNode convertPropertyNaming(
      ObjectMapper objectMapper, JsonNode json, Function<String, String> translator) throws JsonProcessingException {
    if(json.isValueNode()) {
      return json;
    }
    if(json.isArray()) {
      ArrayNode node = objectMapper.createArrayNode();
      for (JsonNode jsonNode : json) {
        node.addRawValue(new RawValue(convertPropertyNaming(objectMapper, jsonNode, translator)));
      }
      return node;
    }
    ObjectNode node = objectMapper.createObjectNode();
    Iterator<Map.Entry<String, JsonNode>> it = json.fields();
    while(it.hasNext()) {
      Map.Entry<String, JsonNode> entry = it.next();
      String name = entry.getKey();
      JsonNode value = entry.getValue();
      node.putRawValue(translator.apply(name), new RawValue(convertPropertyNaming(objectMapper, value, translator)));
    }
    ObjectWriter writer = objectMapper.writer();
    return node;
  }

}
